package com.iotechn.unimall.admin.api.usercard;
import java.util.Date;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.iotechn.unimall.biz.service.distribution.DistributionBizService;
import com.iotechn.unimall.core.exception.AdminServiceException;
import com.iotechn.unimall.core.exception.AppServiceException;
import com.iotechn.unimall.core.exception.ExceptionDefinition;
import com.iotechn.unimall.core.exception.ServiceException;
import com.iotechn.unimall.core.notify.SMSClient;
import com.iotechn.unimall.core.util.GeneratorUtil;
import com.iotechn.unimall.core.util.MoneyUtils;
import com.iotechn.unimall.core.util.RomCodeUtil;
import com.iotechn.unimall.data.domain.*;
import com.iotechn.unimall.data.enums.*;
import com.iotechn.unimall.data.enums.card.SellCardOperType;
import com.iotechn.unimall.data.mapper.*;
import com.iotechn.unimall.data.model.Page;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;


@Service
public class AdminUserCardServiceImpl implements AdminUserCardService {
    @Autowired
    private UserCardMapper userCardMapper;
    @Autowired
    private CardMapper cardMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private CardOrderMapper cardOrderMapper;
    @Autowired
    private CardOrderDetailMapper cardOrderDetailMapper;
    @Autowired
    private OrderMapper orderMapper;
    @Value("${com.iotechn.unimall.machine-no}")
    private String MACHINE_NO;

    @Value("${com.iotechn.unimall.env}")
    private String ENV;
    @Autowired
    private SMSClient aliyunSMSClient;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean productCard(Long adminId, Long id) throws ServiceException {

        CardDO cardDO = cardMapper.selectById(id);
        if (cardDO.getCardUse() == CardUseType.ACTIVE.getCode()) {
            throw new AdminServiceException(ExceptionDefinition.CARD_CHECK_EXIST);
        }
        CardDO cardDO1 = new CardDO();
        cardDO1.setId(cardDO.getId());
        cardDO1.setCardUse(CardUseType.ACTIVE.getCode());
        cardMapper.updateById(cardDO1);
        List<UserCardDO> userCardDOList = new ArrayList<UserCardDO>();
        int size = cardDO.getTotal();
        for (int i = 0; i < size; i++) {
            UserCardDO userCardDO = new UserCardDO();
            userCardDO.setMoney(cardDO.getMoney());
            userCardDO.setCardId(cardDO.getId());
            //随机生成
            String cardNo="";
            int ramCount=0;
            userCardDO.setCardSecret(RomCodeUtil.getRandomNickname(10));
            userCardDO.setStatus(UserCardStatusType.LOCK.getCode());
            userCardDO.setTitle(cardDO.getTitle());
            userCardDO.setGmtCreate(new Date());
            userCardDO.setGmtUpdate(new Date());
            userCardDOList.add(userCardDO);
        }
        return userCardMapper.batchInsertList(userCardDOList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized String  update(Long id, Long userId, String phone, Long storeId,Long storeSkuid,Integer amount,Long adminId) throws ServiceException {
        Double amountTmp = 0d;
        UserCardDO userCardDOOld = userCardMapper.selectById(id);
        if(UserCardStatusType.RECHAGE.getCode() == userCardDOOld.getStatus().intValue()){
            throw new AdminServiceException(ExceptionDefinition.CARD_CHECK_DATA_FAILED);
        }
        UserDO userDO = userMapper.selectById(userId);
        Date now = new Date();
        if (userDO != null && StringUtils.isEmpty(userDO.getPhone())) {
            userDO.setPhone(phone);
            userDO.setId(userId);
            userMapper.updateById(userDO);
        }
        //修改卡状态
        if (userCardDOOld != null) {
            UserCardDO userCardDO = new UserCardDO();
            userCardDO.setId(id);
            userCardDO.setUserId(userId);
            userCardDO.setStatus(2);
            userCardDO.setGmtUpdate(now);
            userCardDO.setUsageTime(now);
            userCardDO.setStoreId(storeId);
            int result = 0;
            if (userCardMapper.updateById(userCardDO) > 0){
                return "ok";

            }

            return "ok";
        }
        throw new AdminServiceException(ExceptionDefinition.PARAM_CHECK_FAILED);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String delete(Long id, Long adminId) throws ServiceException {
        if (userCardMapper.deleteById(id) > 0) {
            return "ok";
        }
        return "fail";
    }


    @Override
    public List<UserCardDO> queryToExcel(Long adminId, Long cardId) {
        EntityWrapper wrapper = new EntityWrapper();
        wrapper.eq("card_id", cardId);
        List<UserCardDO> userCardDOList = userCardMapper.selectList(wrapper);
        return userCardDOList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized String activationCard(Long id,String cardNo, Long storeId, Long storeSkuId,Integer amount,Long adminId) throws ServiceException {
        UserCardDO card= userCardMapper.selectById(id);
        if(UserCardStatusType.RECHAGE.getCode() == card.getStatus().intValue()){
            throw new AdminServiceException(ExceptionDefinition.CARD_CHECK_DATA_FAILED);
        }
        if(card == null){
            throw new AdminServiceException(ExceptionDefinition.CARD_CHECK_DATA_FAILED);
        }
        if(StringUtils.isEmpty(cardNo)){
            throw new AdminServiceException(ExceptionDefinition.CARD_NO_CARDNO);
        }
        List<UserCardDO> userCardDOS = userCardMapper.selectList(new EntityWrapper<UserCardDO>().eq("card_no", cardNo));
        if(userCardDOS != null && userCardDOS.size() > 0 && org.apache.commons.lang3.StringUtils.isEmpty(card.getCardNo())){
            throw new AdminServiceException(ExceptionDefinition.CARD_NO_EXITIS);
        }
        Double cardMoney = 0d;
        if(card.getMoney() != null){
            cardMoney = MoneyUtils.div(card.getMoney() != null ? card.getMoney().doubleValue() : 0d,100d,2);
        }
        Double cardAmount = 0d;
        if(amount != null){
            cardAmount = MoneyUtils.div(amount.doubleValue(),100d,2);
        }
        Integer balance =card.getMoney() + amount;
        Integer realBalance =card.getMoney();
        card.setCardNo(cardNo);
        card.setStatus(UserCardStatusType.ACTIVE.getCode());
        card.setStoreId(storeId);
        card.setGmtUpdate(new Date());
        card.setActivateTime(new Date());
        Integer integer = userCardMapper.updateById(card);

        if(integer<1){
            throw new AdminServiceException(ExceptionDefinition.CARD_CHECK_DATA_FAILED);
        }
        return "ok";
    }


    @Override
    public String updateCard(Long cardId, Integer money, Long adminId) throws ServiceException {
        List<UserCardDO> userCardDOS = userCardMapper.selectList(new EntityWrapper<UserCardDO>().eq("id", cardId));
        if(userCardDOS == null || userCardDOS.size() < 1){
            throw new AdminServiceException(ExceptionDefinition.CARD_EXITIS);
        }
        UserCardDO userCardDO = userCardDOS.get(0);
        if(userCardDO.getStatus().intValue() != UserCardStatusType.LOCK.getCode()){
            throw new AdminServiceException(ExceptionDefinition.CANNOT_UPDATE_CARD);
        }
        userCardDO.setMoney(money);
        Integer integer = userCardMapper.updateById(userCardDO);
        if(integer != 1){
            throw new AdminServiceException(ExceptionDefinition.CARD_CHECK_DATA_FAILED);
        }
        return "ok";
    }

    @Override
    public Integer cardBatchUpdate(Long startCard, Long endCard, Long storeId, Long adminId) throws ServiceException {
        if(startCard == null || endCard == null){
            throw new AdminServiceException(ExceptionDefinition.CARD_NOT_EXIST);
        }

        Integer integer = userCardMapper.updateBatchByNo(storeId, startCard+"", endCard+"");
        return integer;
    }

    /**
     * 后台下单  激活 / 绑定
     * @param
     */
    public void  makeCardOrderByAdmin(List<UserCardDO> cards,Integer actualPrice,String paychannel,Integer operType,UserDO user,Long storeId,Long adminid) throws AppServiceException {
            //加上乐观锁，防止用户重复提交订单
            String orderNo = GeneratorUtil.genCardOrderId(MACHINE_NO, ENV);
            CardOrderDO orderDO = new CardOrderDO();
            orderDO.setActualPrice(actualPrice);
            orderDO.setPayPrice(actualPrice);
            orderDO.setPaymentPrice(0);
            orderDO.setChangePrice(0);
            orderDO.setSmallPrice(0);
            orderDO.setChannel("ADMINBG");
            orderDO.setStatus(OrderStatusType.COMPLETE.getCode());
            orderDO.setSonStatus(0);
            orderDO.setCardOrderNo(orderNo);
            orderDO.setPayChannel(paychannel);
            orderDO.setGmtPay(new Date());
            orderDO.setOperType(operType);
            if(SellCardOperType.BINDING.getCode() == operType.intValue()){
                if(user == null || org.apache.commons.lang3.StringUtils.isEmpty(user.getPhone()) ){
                    throw new AppServiceException(ExceptionDefinition.SELL_CARD_BINGDING_ERROR);
                }
                orderDO.setCardUserName(user.getNickname());
                orderDO.setCardUserId(user.getId());
                orderDO.setCardPhone(user.getPhone());
            }
            orderDO.setStoreId(storeId);
            orderDO.setStoreUserId(adminid);
            orderDO.setGmtUpdate(new Date());
            orderDO.setGmtCreate(new Date());
            Integer insert = cardOrderMapper.insert(orderDO);
            if(insert < 1){
                throw new AppServiceException(ExceptionDefinition.ORDER_STORE_REPEAT_SUBMISSION);
            }
            List<String> cardNos = cards.stream().map(UserCardDO::getCardNo).collect(Collectors.toList());
            List<UserCardDO> userCardDOS = userCardMapper.selectList(new EntityWrapper<UserCardDO>().in("card_no",cardNos));
            Map<String, UserCardDO> userCardDOMap = userCardDOS.stream().collect(Collectors.toMap(UserCardDO::getCardNo, cardDO -> cardDO, (k1, k2) -> k1));
            for (UserCardDO card : cards){
                if(SellCardOperType.NOUSER.getCode() == operType.intValue()){
                    UserCardDO userCardDO = userCardDOMap.get(card.getCardNo());
                    if(userCardDO != null){
                        if(CardUseType.ACTIVE.getCode() == userCardDO.getStatus().intValue()){
                            throw new AppServiceException(ExceptionDefinition.CARD_IS_USE);
                        }
                    }
                }

            }
    }
}